package com.mxpio.erp.oa.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mxpio.erp.common.enums.BizExceptionEnums;
import com.mxpio.erp.common.enums.OaEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.handler.WorkerOrderStatusManager;
import com.mxpio.erp.common.model.request.BpmnSubmitRequest;
import com.mxpio.erp.common.oa.entity.OaLeave;
import com.mxpio.erp.common.oa.service.OaLeaveService;
import com.mxpio.erp.common.util.AssertUtil;
import com.mxpio.erp.common.util.CloneUtil;
import com.mxpio.erp.common.util.JacksonMapUtils;
import com.mxpio.erp.common.util.MapUtil;
import com.mxpioframework.camunda.service.BpmnFlowService;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.security.util.SecurityUtils;
import com.mxpioframework.system.service.PojoDictParseService;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

;

@Service
public class OaLeaveServiceImpl extends BaseServiceImpl<OaLeave> implements OaLeaveService {

    @Resource
    private BpmnFlowService bpmnFlowService;

    @Resource
    private PojoDictParseService dictService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OaLeave doSave(OaLeave oaLeave) {
        oaLeave.setOrderStatus(OaEnums.OrderStatus.NEW.getCode());
        oaLeave.setBpmnStatus(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode());
        this.save(oaLeave);

        return oaLeave;
    }

    @Override
    @Transactional
    public OaLeave submit(BpmnSubmitRequest request) {

        AssertUtil.notEmpty(request.getBizNo(), BizExceptionEnums.PARAM_NOT_NULL, "bizNo");

        OaLeave oaLeaveOrder = this.getById(OaLeave.class, request.getBizNo());

        AssertUtil.notNull(oaLeaveOrder, BizExceptionEnums.ORDER_NOT_FOUND);

        WorkerOrderStatusManager.submitValidate(oaLeaveOrder.getOrderStatus(), oaLeaveOrder.getBpmnStatus());

        //1. 开启工作流
        OaLeave oaLeave = parseDict(oaLeaveOrder);
        Map<String, Object> workFlowParam = JacksonMapUtils.convertObjectToMap(oaLeave);
        ProcessInstance processInstance = bpmnFlowService.startWithFormByKey(request.getKey(), SecurityUtils.getLoginUsername(), request.getBusinessKey(), workFlowParam);
        //2. 更新工单
        oaLeaveOrder.setOrderStatus(OaEnums.OrderStatus.UNDER_REVIEW.getCode());
        oaLeaveOrder.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
        oaLeaveOrder.setProcessInstanceId(processInstance.getId());
        this.update(oaLeaveOrder);

        return oaLeaveOrder;
    }

    @Override
    @Transactional
    public OaLeave audit(BpmnSubmitRequest request) {

        AssertUtil.notEmpty(request.getBizNo(), BizExceptionEnums.PARAM_NOT_NULL, "bizNo");

        OaLeave oaLeaveOrder = this.getById(OaLeave.class, request.getBizNo());

        AssertUtil.notNull(oaLeaveOrder, BizExceptionEnums.ORDER_NOT_FOUND);

        //当前操作允许的状态
        List<String> requestPassStatus = Lists.newArrayList(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode(),
                OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());

        AssertUtil.isTrue(requestPassStatus.contains(request.getBpmnStatus()), BizExceptionEnums.ORDER_AUDIT_STATUS_ERROR);

        //被审批工单允许的状态
        List<String> orderPassStatus = Lists.newArrayList(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());

        AssertUtil.isTrue(orderPassStatus.contains(oaLeaveOrder.getBpmnStatus()),BizExceptionEnums.ORDER_UNABLE_AUDIT_BY_STATUS,oaLeaveOrder.getBpmnStatus());

        if (request.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())) {
            oaLeaveOrder.setOrderStatus(OaEnums.OrderStatus.DONE.getCode());
            oaLeaveOrder.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
        } else {
            oaLeaveOrder.setOrderStatus(OaEnums.OrderStatus.CLOSED.getCode());
            oaLeaveOrder.setBpmnStatus(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());
        }

        this.update(oaLeaveOrder);

        return oaLeaveOrder;
    }


    private OaLeave parseDict(OaLeave oaLeaveOrder) {
        OaLeave cloneOaLeave = CloneUtil.deepClone(oaLeaveOrder, OaLeave.class);
        Result<OaLeave> result = Result.OK(cloneOaLeave);
        dictService.parseDictResult(result);
        return result.getResult();
    }

}